package com.csii.autocode.service;

import com.csii.autocode.config.ReadConfig;
import com.csii.autocode.config.ReadTemplate;
import com.csii.autocode.utils.ReadFile;
import com.csii.autocode.utils.ConfigurationUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;


public class CommonCodeGenerate {
    private static final Logger logger = LoggerFactory.getLogger(CommonCodeGenerate.class);

    protected static String outputEncode = "UTF-8";

    protected List<String> outStrs = new ArrayList<>();

    //生成目标路径下所有文件
    protected void createAllFiles(ReadTemplate parama, String paramString, Map<String, Object> paramMap) throws Exception {
        logger.debug("--------generate----projectPath--------" + paramString);
        for (byte b = 0; b < parama.getTemplateRootDirs().size(); b++) {
            File file = parama.getTemplateRootDirs().get(b);
            createCodeFiles(paramString, file, paramMap, parama);
        }
    }

    //遍历生成代码文件
    protected void createCodeFiles(String paramString, File paramFile, Map<String, Object> paramMap, ReadTemplate parama) throws Exception {
        if (paramFile == null)
            throw new IllegalStateException("'templateRootDir' must be not null");
        logger.info("  load template from templateRootDir = '" + paramFile.getAbsolutePath() + "',stylePath ='" + parama.getStylePath() + "',  out GenerateRootDir:" + ReadConfig.getProjectPath());
        List<File> list = ReadFile.getFileList(paramFile);
        logger.debug("----srcFiles----size-----------" + list.size());
        logger.debug("----srcFiles----list------------" + list.toString());
        for (byte b = 0; b < list.size(); b++) {
            File file = list.get(b);
            createCodeFile(paramString, paramFile, paramMap, file, parama);
        }
    }

    //生成目标文件
    protected void createCodeFile(String paramString, File paramFile1, Map<String, Object> paramMap, File paramFile2, ReadTemplate parama) throws Exception {
        logger.debug("-------templateRootDir--" + paramFile1.getPath());
        logger.debug("-------srcFile--" + paramFile2.getPath());
        String str = ReadFile.cutString(paramFile1, paramFile2);
        try {
            logger.debug("-------templateFile--" + str);
            String str1 = getFileString(paramMap, str, parama);
            if(str1==null)
                return;
            logger.debug("-------outputFilepath--" + str1);
            if (str1.startsWith("java")) {
                String str2 = paramString + File.separator + ReadConfig.getSourceRootPackage().replace(".", File.separator);
                String str3 = str2;
                str1 = str1.substring("java".length());
                str1 = str3 + str1;
                logger.debug("-------java----outputFilepath--" + str1);
                createFile(str, str1, paramMap, parama);
            } else if (str1.startsWith("webapp")) {
                String str2 = paramString + File.separator + ReadConfig.getWebrootPackage().replace(".", File.separator);
                String str3 = str2;
                str1 = str1.substring("webapp".length());
                str1 = str3 + str1;
                logger.debug("-------webapp---outputFilepath---" + str1);
                createFile(str, str1, paramMap, parama);
            }
        } catch (Exception exception) {
            logger.error(exception.toString(), exception);
        }
    }

    //生成对应的.java/.vue文件
    protected void createFile(String paramString1, String paramString2, Map<String, Object> paramMap, ReadTemplate parama) throws Exception {
        if (paramString2.endsWith("i"))
            paramString2 = paramString2.substring(0, paramString2.length() - 1);
        Template template = getTemplate(paramString1, parama);
        template.setOutputEncoding(outputEncode);
        //去除多余斜杠
        paramString2 = paramString2.replace("\\\\","\\").replace("\\\\","\\");
        File file = ReadFile.getFile(paramString2);
        logger.info("[generate]\t template:" + paramString1 + " ==> " + paramString2);
        ConfigurationUtil.writeFile(template, paramMap, file, outputEncode);
        if (!isStartsWith(file))
            this.outStrs.add(paramString2);
        if (isStartsWith(file))
            a(file, "#segment#");
    }

    //获取模板对象
    protected Template getTemplate(String paramString, ReadTemplate parama) throws IOException {
        return ConfigurationUtil.getConfiguration(parama.getTemplateRootDirs(), outputEncode, paramString).getTemplate(paramString);
    }

    protected boolean isStartsWith(File paramFile) {
        if (paramFile.getName().startsWith("[1-n]"))
            return true;
        return false;
    }

    /**
     * 代理扫描路径遍历-漏洞修复 134行
     */
    private static Pattern FilePattern =  Pattern.compile("[\\\\/:*?\"<>|]");
    public static String fileNameFilter(String str){
        return str==null?null:FilePattern.matcher(str).replaceAll("");
    }

    //onetomany
    protected void a(File paramFile, String paramString) {
        InputStreamReader inputStreamReader = null;
        BufferedReader bufferedReader = null;
        ArrayList<OutputStreamWriter> arrayList = new ArrayList();
        try {
            inputStreamReader = new InputStreamReader(new FileInputStream(paramFile), "UTF-8");
            bufferedReader = new BufferedReader(inputStreamReader);
            boolean bool = false;
            OutputStreamWriter outputStreamWriter = null;
            String str;
            while ((str = bufferedReader.readLine()) != null) {
                if (str.trim().length() > 0 && str.startsWith(paramString)) {
                    String str1 = str.substring(paramString.length());
                    String str2 = paramFile.getParentFile().getAbsolutePath();
                    str1 = str2 + File.separator + str1;
                    logger.info("[generate]\t split file:" + paramFile.getAbsolutePath() + " ==> " + str1);

                    str1 = fileNameFilter(str1);
                    outputStreamWriter = new OutputStreamWriter(new FileOutputStream(str1), "UTF-8");
                    arrayList.add(outputStreamWriter);
                    this.outStrs.add(str1);
                    bool = true;
                    continue;
                }
                if (bool)
                    outputStreamWriter.append(str + "\r\n");
            }
            for (byte b = 0; b < arrayList.size(); b++)
                ((Writer) arrayList.get(b)).close();
            bufferedReader.close();
            inputStreamReader.close();
            logger.debug("[generate]\t delete file:" + paramFile.getAbsolutePath());
            isDeleted(paramFile);
        } catch (FileNotFoundException fileNotFoundException) {
            logger.error(fileNotFoundException.getMessage());
        } catch (IOException ioException) {
            logger.error(ioException.getMessage());
        } finally {
            try {
                if (bufferedReader != null)
                    bufferedReader.close();
                if (inputStreamReader != null)
                    inputStreamReader.close();
                if (arrayList.size() > 0)
                    for (byte b = 0; b < arrayList.size(); b++) {
                        if (arrayList.get(b) != null)
                            ((Writer) arrayList.get(b)).close();
                    }
            } catch (IOException ioException) {
                logger.error(ioException.getMessage());
            }
        }
    }

    protected static String getFileString(Map<String, Object> paramMap, String paramString, ReadTemplate parama) throws Exception {
        String str1 = paramString;
        int i = -1;
        if ((i = paramString.indexOf('@')) != -1) {
            str1 = paramString.substring(0, i);
            String str = paramString.substring(i + 1);
            Object object = paramMap.get(str);
            if (object == null) {
                System.err.println("[not-generate] WARN: test expression is null by key:[" + str + "] on template:[" + paramString + "]");
                return null;
            }
            if (!"true".equals(String.valueOf(object))) {
                logger.error("[not-generate]\t test expression '@" + str + "' is false,template:" + paramString);
                return null;
            }
        }
        Configuration configuration = ConfigurationUtil.getConfiguration(parama.getTemplateRootDirs(), outputEncode, "/");
        str1 = ConfigurationUtil.getTemplateString(str1, paramMap, configuration);
        String str2 = parama.getStylePath();
        if (str2 != null && str2 .length() >0)
            str1 = str1.substring(str2.length() + 1);
        String str3 = str1.substring(str1.lastIndexOf("."));
        String str4 = str1.substring(0, str1.lastIndexOf(".")).replace(".", File.separator);
        str1 = str4 + str3;
        return str1;
    }

    //是否删除
    protected static boolean isDeleted(File paramFile) {
        boolean bool = false;
        byte b = 0;
        while (!bool && b++ < 10) {
            System.gc();
            bool = paramFile.delete();
        }
        return bool;
    }

    //字符串切割
    protected static String stringCut(String paramString1, String paramString2) {
        boolean bool1 = true;
        boolean bool2 = true;
        while (true) {
            int bool = (paramString1.indexOf(paramString2) == 0) ? 1 : 0;
            int i = (paramString1.lastIndexOf(paramString2) + 1 == paramString1.length()) ? paramString1.lastIndexOf(paramString2) : paramString1.length();
            paramString1 = paramString1.substring(bool, i);
            bool1 = (paramString1.indexOf(paramString2) == 0) ? true : false;
            bool2 = (paramString1.lastIndexOf(paramString2) + 1 == paramString1.length()) ? true : false;
            if (!bool1 && !bool2)
                return paramString1;
        }
    }
}
